//
//  ViewController.m
//  NSNotificationDemo
//
//  Created by wanglei on 17/2/18.
//  Copyright © 2017年 wanglei. All rights reserved.
//

#import "ViewController.h"
#import "newViewController.h"

@interface ViewController ()

@end

@implementation ViewController

- (IBAction)clickBtn:(UIButton *)sender {
    newViewController *newCtr = [[newViewController alloc]init];
    [self.navigationController pushViewController:newCtr animated:YES];
}



- (void)viewDidLoad {
    [super viewDidLoad];
    [self ListeningToNotification1];
    [self ListeningToNotification2];
    [self ListeningToNotification3];
    [self ListeningToNotification4];
    [self ListeningToNotification5];
    
}


// 发送通知
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    
//    [self btn1Click];
    
    UIButton *btn = [[UIButton alloc]initWithFrame:CGRectMake(50, 10, 30, 20)];
    [btn setTitle:@"wangLei" forState:UIControlStateNormal];
  //  [self btn2Click:btn];
    
   // [self btn3Click];
    
  //  [self btn4Click];
   
    
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    [queue addOperationWithBlock:^{
        [self btn5Click];
        [NSThread sleepForTimeInterval:3];
        NSLog(@"1目前的queue所在的线程为%@",[NSThread currentThread]);
    }];

    NSLog(@"这是通知后面的代码,按照通知是同步的道理,应该在通知完成回调之后才会执行");
    
}




/*----------------------- 一 --------- 不传递参数, 最常用的一种 ------------------------------------*/

// 第一步:注册通知
- (void)ListeningToNotification1{
    //监听
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(noti1) name:@"noti1" object:nil];
}

// 第二部:发送通知
-(void)btn1Click{
    [[NSNotificationCenter defaultCenter] postNotificationName:@"noti1" object:nil];
}

//调用方法
-(void)noti1{
    NSLog(@"接收 不带参数的消息");
}




/*--------------------- 二 -------------- 使用监听一方的调用方法时 传递消息  -------------------------*/

// 第一步:注册通知
- (void)ListeningToNotification2{
    
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(noti2:) name:@"noti2" object:nil];
}

// 第二部:发送通知(可以跨控制器进行发送)

-(void)btn2Click:(UIButton *)btn
{
    [[NSNotificationCenter defaultCenter] postNotificationName:@"noti2" object:[NSString stringWithFormat:@"%@",btn.titleLabel.text]];
}

//调用方法
-(void)noti2:(NSNotification *)noti
{
    //使用object处理消息
    NSString *info = [noti object];
    NSLog(@"接收 object传递的消息：%@",info);
}




/*-------------------- 三 ----------- 使用发送通知一方的userInfo 传递消息  --------------------------------*/

// 第一步:注册通知
-(void)ListeningToNotification3{
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(noti3:) name:@"noti3" object:nil];
}

//第二步:发送通知

-(void)btn3Click{
    NSDictionary *dic = [NSDictionary dictionaryWithObject:@"wangLei在这里" forKey:@"param"];
    // 我把方法的object都设为了nil。那么这个参数起到什么作用呢？这个参数有点像二次确认的意思，就是在同一个通知name的情况下还可以通过object再次进行细分通知。就拿上面这个小demo说，如果object为空，接收方会接受所有名字为giveName的通知。但是如果object不为空，接收方就会只接收名字为giveName的而且object正确的通知
    
    [[NSNotificationCenter defaultCenter] postNotificationName:@"noti3" object:nil userInfo:dic];
}


//调用方法
-(void)noti3:(NSNotification *)noti
{
    //使用userInfo处理消息
    NSDictionary  *dic = [noti userInfo];
    NSString *info = [dic objectForKey:@"param"];
    NSLog(@"接收 userInfo传递的消息：%@线程为 %@",info,[NSThread currentThread]);
}

// 最后一步:移除通知
-(void)dealloc
{
    //移除观察者，Observer不能为nil
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

/*---------------------- 四 ------ 使用block接收通知-------------------------------*/

//第一步:注册通知
- (void)ListeningToNotification4{
[[NSNotificationCenter defaultCenter]addObserverForName:@"noti4" object:nil queue:nil usingBlock:^(NSNotification *not){
    //使用userInfo处理消息
    NSDictionary  *dic = [not userInfo];
    NSString *info = [dic objectForKey:@"param"];
    NSLog(@"使用block接收传递的消息：%@",info);
}];
}

//第二步:发送通知
-(void)btn4Click{
    [NSThread sleepForTimeInterval:3];
    NSLog(@"这是通知里面执行的代码,这里的代码正常情况下要执行完之后,才能执行通知之后的代码");
    NSDictionary *dic = [NSDictionary dictionaryWithObject:@"wangLei" forKey:@"param"];
    // 我把方法的object都设为了nil。那么这个参数起到什么作用呢？这个参数有点像二次确认的意思，就是在同一个通知name的情况下还可以通过object再次进行细分通知。就拿上面这个小demo说，如果object为空，接收方会接受所有名字为giveName的通知。但是如果object不为空，接收方就会只接收名字为giveName的而且object正确的通知
    [[NSNotificationCenter defaultCenter] postNotificationName:@"noti4" object:nil userInfo:dic];
}



/*---------------------- 四 ------ NSNotificationQueue 的使用-------------------------------*/

// 第一步:注册通知
- (void)ListeningToNotification5{
    /**
     *  注册一个通知
     *
     */
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(getNotification:) name:@"notificationMethon" object:nil];
    
}


// 发出通知

- (void)btn5Click{
    
//    [[NSNotificationCenter defaultCenter] postNotificationName:@"notificationMethon" object:nil userInfo:@{@"key":@"value"}];
    
    NSNotification *notifacation = [[NSNotification alloc]initWithName:@"notificationMethon" object:nil userInfo:@{@"key":@"value1"}];
    [[NSNotificationQueue defaultQueue] enqueueNotification:notifacation postingStyle:NSPostNow];
}

//
-(void)getNotification:(NSNotification *)info{
    NSDictionary *dict = info.userInfo;
    NSLog(@"这是通知里面执行的代码,这里的代码正常情况下要执行完之后,才能执行通知之后的代码;当前执行任务的线程为%@",[NSThread currentThread]);
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}


@end
